package com.ztr.suanfa.md5;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.UUID;

public class SFMD5 {

    public static void main(String[] args) {
        String password = "123456";
//        String passwordMd5Str = md51(password);
        String passwordMd5Str = md52(password);
        System.out.println("加密前: " + password);
        System.out.println("加密后: " + passwordMd5Str);
    }

    /**
     * 获取 MD5 算法实例
     * 获取需要加密的字符内容对应的的字节信息，可指定编码方式
     * 对得到的字节信息使用 MD5 算法处理，得到加密后的字节
     * 将加密后的字节转化为 16 进制字符串
     * 返回加密后的字符串信息
     * @param data
     * @return
     */
    public static String md51(String data) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 将输入字符串data转换为UTF-8编码的字节数组，然后计算其MD5哈希值。计算的结果是一个字节数组，存储在md5变量中。
            byte[] md5 = md.digest(data.getBytes(StandardCharsets.UTF_8));
            // 将处理后的字节转成 16 进制，得到最终 32 个字符
            StringBuilder sb = new StringBuilder();
            for (byte b : md5) {
                // 对于每个字节b，使用String.format方法将其转换为两位的十六进制字符串，并追加到StringBuilder对象sb中。
                // %02x是格式说明符，表示将字节转换为两位的十六进制数，不足两位时前面补零。
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 使用盐值可以进一步提升 MD5 加密算法安全性，降低破解风险。
     * @param data
     * @return
     */
    public static String md52(String data) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 加盐处理，需要将对应的盐记录，用于验证密码
            int randomNum = new SecureRandom().nextInt(1000);
            byte[] md5 = md.digest((data + randomNum).getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : md5) {
                //sb.append(Integer.toHexString(b & 0xff));
                // 字符串格式转成 16 进制
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 产生随机的盐值（以随机生成的UUID前四位为例）
     * @param data
     * @return
     */
    public static String md53(String data) {
        try {
            //产生随机的盐值（以随机生成的UUID前四位为例）
            String sale = UUID.randomUUID().toString().substring(0,4);
            //创建基于MD5算法的消息摘要对象
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 加盐处理，需要将对应的盐记录，用于验证密码
            int randomNum = new SecureRandom().nextInt(1000);
            byte[] md5 = md.digest((data + randomNum + sale).getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : md5) {
                //sb.append(Integer.toHexString(b & 0xff));
                // 字符串格式转成 16 进制
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

}
